<?php
/**
 * 月ごとの予定データＩＤを保持するデータモデル
 */
require_once dirname(__FILE__) . '/../Controller.php';
require_once 'Request/DateTime.php';
require_once 'Session.php';
require_once 'DateMath.php';
require_once APPLICATION_PATH . '/models/Names/Names.php';

/**
 * 月ごとの予定データを予示するモデルクラス
 * @author admin
 * <br /><a href="https://www.evernote.com/shard/s89/sh/6ae9aad8-9b1e-40ea-b723-8afdc9ec74c3/e22c51b375d31fb3ab4810f60c2d35e8">開発メモ</a>
 */
class Models_Calendar_Controller extends Models_Controller
{
	/** 値：イベントカテゴリー定期練習 */
	const VALUE_EVENT_CATEGORY_PERIOD_TRAINING = '定期練習';
	/** 値：イベントカテゴリー対外試合 */
	const VALUE_EVENT_CATEGORY_MATCH = '試合';
	/** 値：イベントカテゴリーレクレーション */
	const VALUE_EVENT_CATEGORY_RECREATION = 'レクレーション';
	/** 値：学年：１年生 */
	const VALUE_GAKUNEN1= '１年生';
	/** 値：学年：2年生 */
	const VALUE_GAKUNEN2= '２年生';
	/** 値：学年：3年生 */
	const VALUE_GAKUNEN3= '３年生';
	/** 値：学年：4年生 */
	const VALUE_GAKUNEN4= '４年生';
	/** 値：学年：5年生 */
	const VALUE_GAKUNEN5= '５年生';
	/** 値：学年：6年生 */
	const VALUE_GAKUNEN6= '６年生';


	/** ハッシュキー：日 */
	const KEY_YOTEIBI = 'YOTEIBI';
	/** ハッシュキー：開始時刻 */
	const KEY_START_TIME = 'START_TIME';
	/** ハッシュキー：終了時刻 */
	const KEY_END_TIME = 'END_TIME';
	/** ハッシュキー：招集学年リスト */
	const KEY_DRAFT_AGE = 'DRAFT_AGE_LIST';
	/** ハッシュキー：活動分類 */
	const KEY_EVENT_CATEGORY = 'EVENT_CATEGORY';
	/** ハッシュキー：お知らせ */
	const KEY_NOTICE = 'NOTICE';
	/** ハッシュキー：ゲーム結果速報リンクよう識別 */
	const KEY_MATCH_LINK = 'MATCH_LINK';
	/** ハッシュキー：集合場所 */
	const KEY_MAP_ID = 'MAP_ID';
	/** ハッシュキー：中止フラグ */
	const KEY_STOP_FLG = 'STOP_FLG';

	/** セッションキー：データセット */
	const SESSION_KEY_DATASET = 'DATASET';

	/** @var $HttpRequest ＨＴＴＰリクエストオブジェクト */
	public $HttpRequest;

	/**
	 * コンストラクタ
	 */
	public function __construct()
	{
		$this->HttpRequest = new Lib_Request_DateTime();
	}

	/**
	 * 指定日のデータセットリストを取得する
	 * @param  $Day
	 */
	public function getDayDataset($Day)
	{
		$aryResultDatasetList = array();
		if ($this->_aryDataSet === FALSE) {
			return $aryResultDatasetList;
		}
		/*** すべてのデータを捜査 */
		foreach ($this->_aryDataSet as $aryData){
			/*** 指定日検出判定 */
			if ( $aryData[self::KEY_YOTEIBI] == $Day) {
				$aryResultDatasetList[] = $aryData;
			}
		}
		return $aryResultDatasetList;
	}

	/**
	 * 予定追加
	 * @param $Yoteibi 予定日
	 * @param $StartTime 集合時刻
	 * @param $EndTime 解散時刻
	 * @param $aryDraftAgeList 招集学年リスト
	 * @param $EventCategory 活動分類
	 * @param $Notice 連絡事項
	 * @param $MapId 集合場所ID
	 * <br /><a href="https://www.evernote.com/shard/s89/sh/792f8681-d331-42f5-9f7d-1d25fa3014d9/56f57c4c573cbd2107db261950770677">開発メモ</a>
	 */
	public function add($Yoteibi, $StartTime, $EndTime, $aryDraftAgeList, $EventCategory, $Notice, $MapId)
	{
		$id = parent::createId();
		$NewDataset
		= $this->_createDataset($id, $Yoteibi, $StartTime, $EndTime, $aryDraftAgeList, $EventCategory, $Notice, $MapId);
		$this->_aryDataSet[] =  $NewDataset;
	}

	/**
	 * 指定予定ＩＤの予定日を年月日の配列で返す
	 */
	public function getDateOfYotei($id)
	{
		$Dataset = $this->_searchId($id);
		/***
		 * IDが存在しなければＦＡＬＳＥを返す
		 */
		if ($Dataset === FALSE){
			return FALSE;
		}
		$YoteiDay = $Dataset[self::KEY_YOTEIBI];
		/***
		 * ファイル名から年月祖取得
		 */
		$yyyymm = basename($this->_strFileName, '.xml');
		$yyyy = substr($yyyymm,0,4);
		$mm = substr($yyyymm, 4,2);

		$aryResult
		= array(
				Lib_Request_DateTime::KEY_YEAR=>$yyyy,
				Lib_Request_DateTime::KEY_MONTH=>$mm,
				Lib_Request_DateTime::KEY_DAY=>$YoteiDay
				);
		return $aryResult;
	}

	/**
	 * データセット編集
	 * @param  $id
	 * @param  $Yoteibi
	 * @param  $StartTime
	 * @param  $EndTime
	 * @param  $aryDraftAgeList
	 * @param  $EventCategory
	 * @param  $MatchLink
	 * @return multitype:unknown string
	 */
	static public function _createDataset($id, $Yoteibi, $StartTime, $EndTime, $aryDraftAgeList, $EventCategory, $Notice, $MapId, $MatchLink='')
	{
		if (is_array($aryDraftAgeList)){
			$sDraftAgeList = implode(',',$aryDraftAgeList);
		}else{
			$sDraftAgeList = $aryDraftAgeList;
		}
		$NewDataset
		= array(
				self::KEY_ID=>$id,
				self::KEY_YOTEIBI=>$Yoteibi,
				self::KEY_START_TIME=>$StartTime,
				self::KEY_END_TIME=>$EndTime,
				self::KEY_DRAFT_AGE=>$sDraftAgeList,
				self::KEY_EVENT_CATEGORY=>$EventCategory,
				self::KEY_NOTICE=>$Notice,
				self::KEY_MAP_ID=>$MapId,
				self::KEY_MATCH_LINK =>''
		);
		return $NewDataset;
	}

	/**
	 * SESSIONからデータセットを編集する
	 * @return Ambigous <multitype:unknown, multitype:string unknown Ambigous <unknown, string> >
	 */
	public static function createDatasetFromSession()
	{
		$sessionKey = get_class();
		$objSession = new Lib_Session($sessionKey);
		$aryDataset = $objSession->getValue(self::SESSION_KEY_DATASET);

		$id = $aryDataset[Names::YOTEIID];
		$Yoteibi = $aryDataset[Names::YOTEIBI];
		$StartTime = $aryDataset[Names::STARTTIMEHOUR].':'.$aryDataset[Names::STARTTIMEMINUTE];
		$EndTime = $aryDataset[Names::ENDTIMEHOUR].':'.$aryDataset[Names::ENDTIMEMINUTE];
		$aryDraftAgeList = $aryDataset[Names::DRAFTAGE];
		$EventCategory = $aryDataset[Names::EVENT_CATEGORY];
		$Notice = $aryDataset[Names::NOTICE];
		$MapId = $aryDataset[Names::ASSEMBLYPLACE];
		$aryNewDataset = self::_createDataset($id, $Yoteibi, $StartTime, $EndTime, $aryDraftAgeList, $EventCategory, $Notice, $MapId);
		foreach ($aryNewDataset as $key=>&$Data) {
			switch ($key) {
				case Names::NOTICE:
					break;
				default:
					if($Data == '') {
						$Data = FALSE;
					}
			}
		}
		return $aryNewDataset;
	}

	/**
	 * HTTPリクエストからデータセットを編集する
	 * <a href="https://www.evernote.com/shard/s89/sh/bcc3f9e9-3bf6-4d20-9492-791ae2644fce/6aa0b9906f92c9c21ed4d1e871b8b7a9">開発メモ </a>
	 */
	public static function createDatasetFromHttpRequest()
	{
		$id = $this->HttpRequest->get(Names::YOTEIID);
		$Yoteibi = $this->HttpRequest->get(Names::YOTEIBI);
		$StartTime = $this->HttpRequest->get(Names::STARTTIMEHOUR).':'.$this->HttpRequest->get(Names::STARTTIMEMINUTE);
		$EndTime = $this->HttpRequest->get(Names::ENDTIMEHOUR).':'.$this->HttpRequest->get(Names::ENDTIMEMINUTE);
		$aryDraftAgeList = $this->HttpRequest->get(Names::DRAFTAGE);
		$EventCategory = $this->HttpRequest->get(Names::EVENT_CATEGORY);
		$Notice = $this->HttpRequest->get(Names::NOTICE);
		$MapId = $this->HttpRequest->get(Names::ASSEMBLYPLACE);
		$aryNewDataset = self::_createDataset($id, $Yoteibi, $StartTime, $EndTime, $aryDraftAgeList, $EventCategory, $Notice, $MapId);
		foreach ($aryNewDataset as &$Data) {
			if($Data == ''){
				$Data = FALSE;
			}
		}
		return $aryNewDataset;
	}

	/**
	 * データ挿入用ＨＴＴＰリクエストバリデートチェック
	 */
	public function validateHttpRequestForInsert()
	{
		$HttpRequest = new Lib_Request_DateTime();
		$this->HttpRequest->ValidRequireList
		= array(
//				Names::YOTEIBI,
				Names::ASSEMBLYPLACE,
				Names::STARTTIMEHOUR,
				Names::STARTTIMEMINUTE,
				Names::ENDTIMEHOUR,
				Names::ENDTIMEMINUTE,
				Names::DRAFTAGE,
				Names::EVENT_CATEGORY,
//				Names::NOTICE,
				);
		$this->HttpRequest->ValidNumericList
		= array(
//				Names::YOTEIBI,
				Names::ASSEMBLYPLACE,
				Names::STARTTIMEHOUR,
				Names::STARTTIMEMINUTE,
				Names::ENDTIMEHOUR,
				Names::ENDTIMEMINUTE,
				);

		$result = $this->HttpRequest->valid();

		/*** 単項テストに問題がなければ相関テストを実施する */
		if ($result === TRUE) {
			/*** 集合解散時刻相関チェック */
			$uTimeStart
			= strtotime(
					'20000101' .
					$this->HttpRequest->get(Names::STARTTIMEHOUR) .
					$this->HttpRequest->get(Names::STARTTIMEMINUTE)
					);
			$uTimeEnd
			= strtotime(
					'20000101' .
					$this->HttpRequest->get(Names::ENDTIMEHOUR) .
					$this->HttpRequest->get(Names::ENDTIMEMINUTE)
					);
			if ($uTimeStart >= $uTimeEnd) {
				$this->HttpRequest->InvalidKey = Names::STARTTIMEHOUR;
				$this->HttpRequest->InvalidReason = Lib_Request::VALUE_INVALID_REASON_INTERRELATED;
				return false;
			}
		}

		return $result;
	}

	/**
	 * HTTPリクエストの値から予定を更新する
	 */
	public function updateFromHttpRequest()
	{
		$aryNewDataset = self::createDatasetFromHttpRequest();
		$result
		= $this->update(
				$aryNewDataset[self::KEY_ID],
				$aryNewDataset[self::KEY_YOTEIBI],
				$aryNewDataset[self::KEY_START_TIME],
				$aryNewDataset[self::KEY_END_TIME],
				$aryNewDataset[self::KEY_DRAFT_AGE],
				$aryNewDataset[self::KEY_EVENT_CATEGORY],
				$aryNewDataset[self::KEY_NOTICE],
				$aryNewDataset[self::KEY_MAP_ID]
				);
		return $result;
	}

	/**
	 * セッションの値から予定を更新する
	 * @return boolean
	 */
	public function updateFromSession()
	{
		$aryNewDataset = self::createDatasetFromSession();
		$result
		= $this->update(
				$aryNewDataset[self::KEY_ID],
				$aryNewDataset[self::KEY_YOTEIBI],
				$aryNewDataset[self::KEY_START_TIME],
				$aryNewDataset[self::KEY_END_TIME],
				$aryNewDataset[self::KEY_DRAFT_AGE],
				$aryNewDataset[self::KEY_EVENT_CATEGORY],
				$aryNewDataset[self::KEY_NOTICE],
				$aryNewDataset[self::KEY_MAP_ID]
		);
		return $result;
	}
	/**
	 * SESSIONの値から予定を追加する
	 */
	public function addFromSession()
	{
		$aryNewDataset = self::createDatasetFromSession();
		$result
		= $this->add(
				$aryNewDataset[self::KEY_YOTEIBI],
				$aryNewDataset[self::KEY_START_TIME],
				$aryNewDataset[self::KEY_END_TIME],
				$aryNewDataset[self::KEY_DRAFT_AGE],
				$aryNewDataset[self::KEY_EVENT_CATEGORY],
				$aryNewDataset[self::KEY_NOTICE],
				$aryNewDataset[self::KEY_MAP_ID]
		);
		return $result;
	}

	/**
	 * HTTPリクエストの値から予定を追加する
	 */
	public function addFromHttpRequest()
	{
		$aryNewDataset = self::createDatasetFromHttpRequest();
		$result
		= $this->add(
				$aryNewDataset[self::KEY_YOTEIBI],
				$aryNewDataset[self::KEY_START_TIME],
				$aryNewDataset[self::KEY_END_TIME],
				$aryNewDataset[self::KEY_DRAFT_AGE],
				$aryNewDataset[self::KEY_EVENT_CATEGORY],
				$aryNewDataset[self::KEY_NOTICE],
				$aryNewDataset[self::KEY_MAP_ID]
		);
		return $result;
	}

	/**
	 * 予定更新
	 * <a href="https://www.evernote.com/shard/s89/sh/7f91e90d-8a5a-4486-a242-b5ca9047b995/cf9933c38d57899bc60773bcc04909cd">開発メモ</a>
	 * @param $id 予定ＩＤ
	 * @param $Yoteibi 予定日
	 * @param $StartTime 集合時刻
	 * @param $EndTime 解散時刻
	 * @param $aryDraftAgeList 招集学年リスト
	 * @param $EventCategory 活動分類
	 * @param $Notice 連絡事項
	 * @param $MapId 集合場所ＩＤ
	 */
	public function update($id, $Yoteibi, $StartTime, $EndTime, $aryDraftAgeList, $EventCategory, $Notice, $MapId)
	{
		/***
		 * 更新前予定取得
		 */
		$aryDataset = $this->searchId($id);
		/*** 未検出判定 */
		if ( $aryDataset === FALSE ) {
			$this->bErrorExists = TRUE;
			return FALSE;
		}
		/***
		 * FALSEが設定されている引数についてはオリジナルの値を使用する
		 */
		/*** ＦＡＬＳＥ判定：予定日 */
		if ($Yoteibi === FALSE){
			$Yoteibi = $aryDataset[self::KEY_YOTEIBI];
		}
		/*** ＦＡＬＳＥ判定：集合時間 */
		if ($StartTime===FALSE){
			$StartTime = $aryDataset[self::KEY_START_TIME];
		}
		/*** ＦＡＬＳＥ判定：解散時間 */
		if ($EndTime===FALSE) {
			$EndTime = $aryDataset[self::KEY_END_TIME];
		}
		/*** ＦＡＬＳＥ判定：招集学年 */
		if ($aryDraftAgeList===FALSE) {
			$aryDraftAgeList = explode(',', $aryDataset[self::KEY_DRAFT_AGE]);
		}
		/*** ＦＡＬＳＥ判定：活動分類 */
		if ($EventCategory === FALSE) {
			$EventCategory = $aryDataset[self::KEY_EVENT_CATEGORY];
		}
		/*** ＦＡＬＳＥ判定：おしらせ */
		if ($Notice === FALSE){
			$Notice = $aryDataset[self::KEY_NOTICE];
		}
		/*** ＦＡＬＳＥ判定：集合場所 */
		if ($MapId===FALSE){
			$MapId = $aryDataset[self::KEY_MAP_ID];
		}
		/*** FALSEが設定されている引数についてはオリジナルの値を使用する END */

		$NewDataset
		= $this->_createDataset($id, $Yoteibi, $StartTime, $EndTime, $aryDraftAgeList, $EventCategory, $Notice, $MapId, '');
		$this->delelte($id);
		$this->_aryDataSet[] = $NewDataset;
	}

	/**
	 * 試合リンク追加
	 */
	public function addMatchLink($id, $MatchLink)
	{
		/*** 予定ＩＤからデータセットを検出する */
		$Dataset = $this->_searchId($id);
		/*** データセット未検出判定 */
		if ($Dataset === FALSE) {
			return FALSE;
		}

		$Dataset[self::KEY_MATCH_LINK] = $MatchLink;
		$this->delelte($id);
		$this->_aryDataSet[] = $Dataset;
	}

	/**
	 * 中止フラグ設定
	 *
	 * @param $id 予定ＩＤ
	 * @param $remove 解除フラグ
	 */
	public function setStopFlg($id, $remove=FALSE)
	{
		$Dataset = &$this->_searchId($id);
		/*** デー民検出判定 */
		if($Dataset === FALSE) {
			return FALSE;
		}
		if ($remove == FALSE) {
			$Dataset[self::KEY_STOP_FLG] = '1';
		} else {
			$Dataset[self::KEY_STOP_FLG] = '0';
		}
	}

	/**
	 * 日付でソートする
	 */
	public function sort()
	{
		$aryBuff = array();
		$i = 1;
		/*** 最長の３１日回す */
		while ($i <= 31){
			$aryBuff2 = array();
			/***日ごとに全データセットを走査 */
			foreach($this->_aryDataSet as $DataInfo){
				/*** 予定日が該当するデータセットをプッシュ */
				if (sprintf('%d',$DataInfo[self::KEY_YOTEIBI]) == $i){
					$aryBuff2[] = $DataInfo;
				}
			}
			if (count($aryBuff2) > 1) {
				//時刻でソートする。
				$aryBuff2 = $this->sortStartTime($aryBuff2);
			}
			$aryBuff = array_merge($aryBuff, $aryBuff2);
			$i ++;
		}
		$this->_aryDataSet = $aryBuff;
	}

	/**
	 * 時刻でソートする
	 */
	public function sortStartTime($aryDataSet)
	{
		$aryStartTimeKeyDataset = array();
		/*** 開始時刻をキーにした配列に変換する　*/
		foreach ($aryDataSet as $Dataset) {
			$key = $Dataset[self::KEY_START_TIME];
			if (strlen($key) == 4) {
				$key = '0' . $key;
			}
			$aryStartTimeKeyDataset[$key] = $Dataset;
		}
		
		ksort($aryStartTimeKeyDataset);
		
		$aryResult = array();
		/*** 数字インデックス配列に戻す。 */
		foreach ($aryStartTimeKeyDataset as $Dataset) {
			$aryResult[] = $Dataset;
		}
		
		return $aryResult;
	}
	
	/**
	 * 予定日取得
	 * ＨＴＴＰリクエストに予定ＩＤが指定されている場合は
	 * 該当予定の予定日を返す
	 * そうでない場合は、ＨＴＴＰリクエストに設定されている年月日を返す
	 * それもない場合は、現在年月日を返す。
	 * 書式：9999年z9月z9日（曜日）
	 */
	public function getYoteibi()
	{
		$objDateMath = new DateMath();
		if ($this->HttpRequest->get(Names::YOTEIID) != ''){
				$aryYoteibi
				= $this->getDateOfYotei($this->HttpRequest->get(Names::YOTEIID));
				if ( $aryYoteibi !== FALSE) {
					$iYoubi = $objDateMath->getDayOfWeek(
							$aryYoteibi[Lib_Request_DateTime::KEY_YEAR]
							. sprintf('%02d', $aryYoteibi[Lib_Request_DateTime::KEY_MONTH])
							. sprintf('%02d', $aryYoteibi[Lib_Request_DateTime::KEY_DAY])
							. '0000'
					);
					$sYoubi = $objDateMath->aryDayOfWeekJp[$iYoubi];
					$sResult
					= $aryYoteibi[Lib_Request_DateTime::KEY_YEAR] . '年'
					. sprintf('%d', $aryYoteibi[Lib_Request_DateTime::KEY_MONTH]) . '月'
					. sprintf('%d', $aryYoteibi[Lib_Request_DateTime::KEY_DAY]) . '日'
					. sprintf('（%s曜日）', $sYoubi);
					return $sResult;
				}
		}

		/***
		 * HTTPリクエストから年月日取得をチャレンジ
		*/
		$sResult = $this->_getDateFromHttpRequest();
		if ($sResult != '') {
			return $sResult;
		}

		/***
		 * 現在年月日を返す
		*/
		$sResult = $this->_getNow();
		return $sResult;
	}

	/**
	 * HTTPリクエストから年月日を返す
	 * 書式：9999年z9月z9日（曜日）
	 */
	protected function _getDateFromHttpRequest()
	{
		if ($this->_isYYYYMMDD_Complete() === FALSE) {
			return '';
		}
		$sResult
		= 	$this->HttpRequest->getYear() . '年'
		. sprintf('%d', $this->HttpRequest->getMonth()) . '月'
		. sprintf('%d', $this->HttpRequest->getDay()) . '日';

		$objDateMath = new DateMath();
		$iYoubi
		= $objDateMath->getDayOfWeek(
				$this->HttpRequest->getYear().
				sprintf('%02d', $this->HttpRequest->getMonth()).
				sprintf('%02d', $this->HttpRequest->getDay()).
				'0000'
		);
		$sYoubi = $objDateMath->aryDayOfWeekJp[$iYoubi];

		$sResult .= '（' . $sYoubi . '曜日）';
		return $sResult;
	}

	/**
	 * HTTPリクエストに年月日がそろっていればＴＲＵＥを返す
	 */
	protected function _isYYYYMMDD_Complete()
	{
		if ($this->HttpRequest->getYear() == '') {
			return FALSE;
		}
		if ($this->HttpRequest->getMonth() == ''){
			return FALSE;
		}
		if ($this->HttpRequest->getDay()==''){
			return FALSE;
		}
		return TRUE;
	}

}
